package kv

import (
	"fmt"

	mse "gitee.com/yrwy/msgo/pkg/errors"
	"gitee.com/yrwy/msgo/pkg/mem"
)

type Map[K comparable] map[K]any

func MakeMap[K comparable]() Map[K] {
	return make(map[K]any)
}

func (m Map[K]) Contains(key K) bool {
	_, ok := m[key]
	return ok
}

// 最佳匹配，如果f返回没有key大于0，则函数返回nil
func (m Map[K]) GetBestMatch(key K, f func(K, K) int) any {
	if v, ok := m[key]; ok {
		return v
	}
	max_match := 0
	var ret_value any = nil
	for k, v := range m {
		r := f(k, key)
		if r > max_match {
			ret_value = v
		}
	}
	return ret_value
}

func (m Map[K]) ToString() string {
	return fmt.Sprintf("%v", m)
}

// 获取子map
func (m Map[K]) GetMap(key K) (Map[K], error) {
	if v, ok := m[key]; ok {
		if r, ok := v.(map[K]any); ok {
			return Map[K](r), nil
		}
		return mem.ConvertMap[K, any](v)
	}
	return nil, mse.ErrNotFound
}

// 尽可能转成字符串
func (m Map[K]) ConvertString(key K) (string, error) {
	if v, ok := m[key]; ok {
		return mem.ConvertString(v)
	}
	return "", mse.ErrNotFound
}

func (m Map[K]) GetString(key K) string {
	v, _ := m.ConvertString(key)
	return v
}

// 尽可能转成int
func (m Map[K]) ConvertInt64(key K) (int64, error) {
	if v, ok := m[key]; ok {
		return mem.ConvertInt64(v)
	}
	return 0, mse.ErrNotFound
}

func (m Map[K]) GetInt64(key K) int64 {
	v, _ := m.ConvertInt64(key)
	return v
}

func (m Map[K]) ConvertUint64(key K) (uint64, error) {
	if v, ok := m[key]; ok {
		return mem.ConvertUint64(v)
	}
	return 0, mse.ErrNotFound
}

func (m Map[K]) GetUint64(key K) uint64 {
	v, _ := m.ConvertUint64(key)
	return v
}

func (m Map[K]) ConvertInt(key K) (int, error) {
	r, e := m.ConvertInt64(key)
	return int(r), e
}

func (m Map[K]) GetInt(key K) int {
	v, _ := m.ConvertInt(key)
	return v
}

func (m Map[K]) ConvertUint(key K) (uint, error) {
	r, e := m.ConvertUint64(key)
	return uint(r), e
}

func (m Map[K]) GetUint(key K) uint {
	v, _ := m.ConvertUint(key)
	return v
}

// 尽可能转成float
func (m Map[K]) ConvertFloat64(key K) (float64, error) {
	if v, ok := m[key]; ok {
		return mem.ConvertFloat64(v)
	}
	return 0, mse.ErrNotFound
}

func (m Map[K]) GetFloat64(key K) float64 {
	v, _ := m.ConvertFloat64(key)
	return v
}

func (m Map[K]) ConvertFloat32(key K) (float32, error) {
	r, e := m.ConvertFloat64(key)
	return float32(r), e
}

func (m Map[K]) GetFloat32(key K) float32 {
	v, _ := m.ConvertFloat32(key)
	return v
}

// 尽可能转成bool
func (m Map[K]) ConvertBool(key K) (bool, error) {
	if v, ok := m[key]; ok {
		return mem.ConvertBool(v)
	}
	return false, mse.ErrNotFound
}
func (m Map[K]) GetBool(key K) bool {
	v, _ := m.ConvertBool(key)
	return v
}

// func (m Map[K]) GetSlice[T any](key K) ([]T, bool) {
// 	if v, ok := m[key]; ok {
// 		if val,ok := v.([]T);ok {
// 			return val, ok
// 		}
// 	}
// 	return false, false
// }
// 参考GetMapSlice

// 尽可能转成complex
func (m Map[K]) ConvertComplex128(key K) (complex128, error) {
	if v, ok := m[key]; ok {
		return mem.ConvertComplex128(v)
	}
	return 0, mse.ErrNotFound
}
func (m Map[K]) GetComplex128(key K) complex128 {
	v, _ := m.ConvertComplex128(key)
	return v
}

func (m Map[K]) ConvertMapSlice(key K) ([]Map[K], error) {
	return GetMapSlice[K, Map[K]](m, key)
}

func (m Map[K]) GetMapSlice(key K) []Map[K] {
	v, _ := GetMapSlice[K, Map[K]](m, key)
	return v
}

func GetMapValue[K comparable, V any](m Map[K], key K) (V, error) {
	if v, ok := m[key]; ok {
		if val, ok := v.(V); ok {
			return val, nil
		}
	}
	var r V
	return r, mse.ErrNotFound
}

func GetMapSlice[K comparable, T any](m Map[K], key K) ([]T, error) {
	if v, ok := m[key]; ok {
		if vals, ok := v.([]T); ok {
			return vals, nil
		}
		return mem.ConvertSlice[T](v)
	}
	return nil, mse.ErrNotFound
}

func RangeMapSlice[K comparable, T any](m Map[K], key K, f func(T) error) error {
	if v, ok := m[key]; ok {
		if vals, ok := v.([]T); ok {
			for _, val := range vals {
				if e := f(val); e != nil {
					return e
				}
			}
			return nil
		}
		if val, ok := v.(T); ok {
			return f(val)
		}
		return mem.RangeSlice[T](v, f)
	}
	return mse.ErrNotFound
}

func RangeMapMap[K, K1 comparable, T any](m Map[K], key K, f func(K1, T) error) error {
	if v, ok := m[key]; ok {
		if m1, ok := v.(map[K1]T); ok {
			for k, val := range m1 {
				if e := f(k, val); e != nil {
					return e
				}
			}
			return nil
		}
		return mem.RangeMap[K1, T](v, f)
	}
	return mse.ErrNotFound
}
